/**
 * 简易状态管理
 */

// 类型映射
const typeMappingData = [
  {id: 'sys01', name: '字符串', code: 'STRING'  , color: '#409eff', enabled: true, mysql: 'VARCHAR' , oracle: 'VARCHAR2', postgres: 'VARCHAR'  , java: 'String' , rust: 'String'         , go: 'string'     , sourceTypes: 'STRING, VARCHAR, VARCHAR2, CHARACTER VARYING, CHAR, CHARACTER'},
  {id: 'sys02', name: '整数'  , code: 'INT'     , color: '#67c23a', enabled: true, mysql: 'INT'     , oracle: 'INT'     , postgres: 'INT'      , java: 'Integer', rust: 'i32'            , go: '*int'       , sourceTypes: 'INT, INTEGER, SERIAL'},
  {id: 'sys03', name: '小数'  , code: 'DECIMAL' , color: '#e6a23c', enabled: true, mysql: 'DECIMAL' , oracle: 'DECIMAL' , postgres: 'DECIMAL'  , java: 'Double' , rust: 'f64'            , go: '*float64'   , sourceTypes: 'DECIMAL, NUMERIC, REAL, DOUBLE'},
  {id: 'sys04', name: '日期'  , code: 'DATETIME', color: '#909399', enabled: true, mysql: 'DATETIME', oracle: 'DATE'    , postgres: 'TIMESTAMP', java: 'Date'   , rust: 'DateTime<Local>', go: '*time.Time' , sourceTypes: 'DATE, DATETIME, TIMESTAMP'},
  {id: 'sys05', name: '大文本', code: 'TEXT'    , color: '#f56c6c', enabled: true, mysql: 'TEXT'    , oracle: 'CLOB'    , postgres: 'TEXT'     , java: 'String' , rust: 'String'         , go: 'string'     , sourceTypes: 'TEXT, CLOB'},
  {id: 'sys06', name: '二进制', code: 'BLOB'    , color: '#f56c6c', enabled: true, mysql: 'BLOB'    , oracle: 'BLOB'    , postgres: 'BYTEA'    , java: 'byte[]' , rust: 'Vec<u8>'        , go: '[]byte'     , sourceTypes: 'BLOB, BYTEA'},
]

// 数据库，编程语言，类型映射目标
const databases = ['postgres', 'mysql', 'oracle']
const languages = ['java', 'rust', 'go']
const typeMappingTargets = [...databases, ...languages]

// 模板配置
const templateDatabaseData = [
  {id: 'sys01', name: '新建表', code: 'CreateTable', color: '#409eff', info: '创建表的SQL语句模板配置',
    postgres: `
-- 删除表
-- DROP TABLE IF EXISTS {{tableName}};
{{set pk = columns.filter(c => c.isPrimary).map(c => c.columnName).join(',') }}
-- 创建表
CREATE TABLE {{tableName}} ({{each columns c}}
  {{c.columnName}} {{c.columnType}}{{if c.columnDefault}} DEFAULT {{c.columnDefault}}{{/if}}{{if c.isNonNull}} NOT NULL{{/if}}, {{/each}}
  PRIMARY KEY ({{pk}})
);

-- 表注释
COMMENT ON TABLE {{tableName}} IS '{{tableComment}}';

-- 列注释{{each columns c}}
COMMENT ON COLUMN {{tableName}}.{{c.columnName}} IS '{{c.columnComment}}';{{/each}}
`.trim(),
    mysql: `
-- 删除表
-- DROP TABLE IF EXISTS {{tableName}};
{{set pk = columns.filter(c => c.isPrimary).map(c => c.columnName).join(',') }}
-- 创建表
CREATE TABLE {{tableName}} ({{each columns c}}
  {{c.columnName}} {{c.columnType}}{{if c.isAutoIncrement}} AUTO_INCREMENT{{/if}}{{if c.isNonNull}} NOT NULL{{/if}}{{if c.columnDefault}} DEFAULT {{c.columnDefault}}{{/if}} COMMENT '{{c.columnComment}}', {{/each}}
  PRIMARY KEY ({{pk}})
) COMMENT '{{tableComment}}';
    `.trim(),
    oracle: `
-- 删除表
-- DROP TABLE {{tableName}};
{{set pk = columns.filter(c => c.isPrimary).map(c => c.columnName).join(',') }}
-- 创建表
CREATE TABLE {{tableName}} ({{each columns c}}
  {{c.columnName}} {{c.columnType}}{{if c.columnDefault}} DEFAULT {{c.columnDefault}}{{/if}}{{if c.isNonNull}} NOT NULL{{/if}}, {{/each}}
  PRIMARY KEY ({{pk}})
);

-- 表注释
COMMENT ON TABLE {{tableName}} IS '{{tableComment}}';

-- 列注释{{each columns c}}
COMMENT ON COLUMN {{tableName}}.{{c.columnName}} IS '{{c.columnComment}}';{{/each}}  
    `.trim()},
  {id: 'sys02', name: '获取表', code: 'FetchTable', color: '#409eff', info: '从数据库获取表信息的SQL配置',
    postgres: `
TODO
`.trim(),
    mysql: `
TODO
    `.trim(),
    oracle: `
TODO
    `.trim()},
  {id: 'sys02', name: '取表名', code: 'DbTables'   , color: '#f56c6c', info: '从数据库获取表信息的SQL配置（TODO）', postgres: '', mysql: '', oracle: ''},
  {id: 'sys03', name: '取列名', code: 'DbColumns'  , color: '#909399', info: '从数据库获取列信息的SQL配置（TODO）', postgres: '', mysql: '', oracle: ''},
]

const templateLanguageData = [
  {id: 'sys01', name: '实体类', code: 'Model' , color: '#409eff', info: '表字段信息生成对应实体类',
    java: `
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fofund.ark.common.annotation.Keyword;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import org.hibernate.validator.constraints.Length;

import java.util.List;
<%
/* 通用字段的特殊处理 */
const modelName = pascal(tableName.split('_')[1])  // 去掉sys_前缀
const createColumns = ['create_by','create_at']
const updateColumns = ['update_by','update_at'] 
const deleteFlag = 'delete_flag'
%>
/**
 * {{_.trimEnd(tableComment, '表')}}
 *
 * @author 何鹏举 {{dayjs().format('YYYY-MM-DD')}}
 */
@Data
@TableName("{{tableName}}") @Schema(description = "{{_.trimEnd(tableComment, '表')}}")
public class {{modelName}} {
   {{each columns c}}
    @Schema(description = "{{c.columnComment}}"){{if c.isPrimary}}
    @TableId(type = IdType.ASSIGN_ID){{/if}}{{if createColumns.indexOf(_.toLower(c.columnName)) > 0}}
    @TableField(fill = FieldFill.INSERT, updateStrategy = FieldStrategy.NEVER){{/if}}{{if updateColumns.indexOf(_.toLower(c.columnName)) > 0}}
    @TableField(fill = FieldFill.UPDATE, insertStrategy = FieldStrategy.NEVER){{/if}}{{if deleteFlag === c.columnName}}
    @TableLogic  @JsonIgnore{{/if}}
    private {{typeMapping(c.columnType, 'java')}} {{camel(c.columnName)}};
   {{/each}}
}
    `.trim(),
    rust: `
use chrono::{DateTime, Local};
use serde::{Deserialize, Serialize};
<%
const modelName = pascal(tableName.split('_')[1])  // 去掉sys_前缀
%>
/// {{_.trimEnd(tableComment, '表')}}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct {{modelName}} {
    {{each columns c}}
    /// {{c.columnComment}}
    pub {{camel(c.columnName)}}: {{if c.isNonNull}}{{typeMapping(c.columnType,'rust')}}{{else}}Option<{{typeMapping(c.columnType,'rust')}}>{{/if}},
    {{/each}}
}
    `.trim(

    ),
    go: `
package models
<%
// 去掉sys_前缀
const modelName = pascal(tableName.split('_')[1])  

// 最大字段长度和类型长度，用于对齐
const maxFieldLength = columns.map(c => pascal(c.columnName).length).reduce( (p,n) => p > n ? p : n)
const maxTypeLength  = columns.map(c => typeMapping(c.columnType, 'go').length).reduce( (p,n) => p > n ? p : n)
log(maxFieldLength, maxTypeLength)
%>
type {{modelName}} struct { {{each columns c}}
    {{_.padEnd(pascal(c.columnName), maxFieldLength)}} {{_.padEnd(typeMapping(c.columnType,'go'),maxTypeLength)}} \`json:"{{camel(c.columnName)}}"\`{{_.padEnd('', maxFieldLength - pascal(c.columnName).length) }} // {{c.columnComment}} {{/each}}
}
    `.trim()},
  {id: 'sys02', name: '服务类', code: 'Service', color: '#67c23a', info: '表字段信息生成对应的Controller、Service、Mapper等扩展',
    java: `
<%
const modelName = pascal(tableName.split('_')[1])  // 去掉sys_前缀
%>

public interface {{modelName}}Mapper extends ArkMapper<{{modelName}}> {

}


@Service @Slf4j
public class {{modelName}}Service extends ArkService<{{modelName}}Mapper, {{modelName}}> {

}


@Tag(name = "{{_.trimEnd(tableComment, '表')}}管理")
@RestController
@RequestMapping("")
public class {{modelName}}Controller extends ArkController<{{modelName}}Service> {
}
    `.trim(),
    rust: `
    
    `.trim(),
    go: ``.trim()},
]

// 常用类型
const typeCommonData = [
  {id: 'sys01', name: '默认字串', code: 'defaultString' , orderNum: 1, isShow: true, type: 'STRING'  , length: 256 , scale: null, remark: null},
  {id: 'sys02', name: '主键'    , code: 'id'            , orderNum: 1, isShow: true, type: 'STRING'  , length: 32  , scale: null, remark: null},
  {id: 'sys03', name: '名称'    , code: 'name'          , orderNum: 1, isShow: true, type: 'STRING'  , length: 256 , scale: null, remark: null},
  {id: 'sys04', name: '整数'    , code: 'int '          , orderNum: 1, isShow: true, type: 'INT'     , length: null, scale: null, remark: null},
  {id: 'sys05', name: '小数'    , code: 'double'        , orderNum: 1, isShow: true, type: 'DECIMAL' , length: 18  , scale: 2   , remark: '最大值趋近1亿亿。注意小数位调整时，总长度也要对应增加（避免最大值降低）'},
  {id: 'sys06', name: '金额'    , code: 'money'         , orderNum: 1, isShow: true, type: 'DECIMAL' , length: 18  , scale: 2   , remark: '最大值趋近1亿亿。注意小数位调整时，总长度也要对应增加（避免最大值降低）'},
  {id: 'sys07', name: '日期字串', code: 'dateString'    , orderNum: 1, isShow: true, type: 'STRING'  , length: 8   , scale: null, remark: '20250205，避免格式差异，可以不存储分隔符-或/'},
  {id: 'sys08', name: '时间字串', code: 'datetimeString', orderNum: 1, isShow: true, type: 'STRING'  , length: 14  , scale: null, remark: '20250205102030，避免格式差异，可以不存储分隔符-或/或:'},
  {id: 'sys09', name: '日期时间', code: 'datetime'      , orderNum: 1, isShow: true, type: 'DATETIME', length: 256 , scale: null, remark: null},
  {id: 'sys10', name: '字典'    , code: 'dict'          , orderNum: 1, isShow: true, type: 'STRING'  , length: 32  , scale: null, remark: null},
  {id: 'sys11', name: '是否'    , code: 'yesNo'         , orderNum: 1, isShow: true, type: 'STRING'  , length: 1   , scale: null, remark: null},
  {id: 'sys12', name: '描述'    , code: 'descText'      , orderNum: 1, isShow: true, type: 'STRING'  , length: 2048, scale: null, remark: null},
]

// 数据字典
const dictData = [
  {id: 'sys01', typeCode: 'gender'     , typeName: '性别', remark: ''},
  {id: 'sys02', typeCode: 'userStatus' , typeName: '用户状态', remark: ''},
  {id: 'sys03', typeCode: 'orderStatus', typeName: '订单状态', remark: ''},
  {id: 'sys04', typeCode: 'payMethod'  , typeName: '支付方式', remark: ''},
]

const itemData = [
  {id: 'sys0101', typeCode: 'gender', itemCode: 'M', itemName: '男'  , orderNum: 1, parentItem: '', itemDesc: '', enableFlag: 'Y', ext01: '', ext02: '', ext03: ''},
  {id: 'sys0102', typeCode: 'gender', itemCode: 'F', itemName: '女'  , orderNum: 2, parentItem: '', itemDesc: '', enableFlag: 'Y', ext01: '', ext02: '', ext03: ''},
  {id: 'sys0103', typeCode: 'gender', itemCode: 'U', itemName: '未知', orderNum: 3, parentItem: '', itemDesc: '', enableFlag: 'Y', ext01: '', ext02: '', ext03: ''},

  {id: 'sys0201', typeCode: 'userStatus', itemCode: '0', itemName: '冻结', orderNum: 1, parentItem: '', itemDesc: '', enableFlag: 'Y', ext01: '', ext02: '', ext03: ''},
  {id: 'sys0202', typeCode: 'userStatus', itemCode: '1', itemName: '正常', orderNum: 2, parentItem: '', itemDesc: '', enableFlag: 'Y', ext01: '', ext02: '', ext03: ''},

  {id: 'sys0301', typeCode: 'orderStatus', itemCode: '0', itemName: '未支付', orderNum: 1, parentItem: '', itemDesc: '', enableFlag: 'Y', ext01: '', ext02: '', ext03: ''},
  {id: 'sys0302', typeCode: 'orderStatus', itemCode: '1', itemName: '已支付', orderNum: 2, parentItem: '', itemDesc: '', enableFlag: 'Y', ext01: '', ext02: '', ext03: ''},
  {id: 'sys0303', typeCode: 'orderStatus', itemCode: '2', itemName: '已取消', orderNum: 3, parentItem: '', itemDesc: '', enableFlag: 'Y', ext01: '', ext02: '', ext03: ''},

  {id: 'sys0401', typeCode: 'payMethod', itemCode: 'onlinePay', itemName: '在线支付', orderNum: 1, parentItem: '', itemDesc: '', enableFlag: 'Y', ext01: '', ext02: '', ext03: ''},
  {id: 'sys0402', typeCode: 'payMethod', itemCode: 'cod'      , itemName: '货到付款', orderNum: 2, parentItem: '', itemDesc: 'cash on delivery', enableFlag: 'Y', ext01: '', ext02: '', ext03: ''},
]

const templateEngineData = [
  {
    id: 'js01',
    name: 'Art',
    lang: 'JavaScript',
    info: 'Art-template是一个简单且超快速的模板引擎，可通过范围预先声明的技术优化模板渲染速度。它实现了接近JavaScript极限的运行时性能。同时，它支持NodeJS和浏览器',
    link: 'https://goofychris.github.io/art-template/zh-cn/docs',
    sample:
      `
        示例
        `.trim()
  },
  {
    id: 'js02',
    name: 'Lodash',
    lang: 'JavaScript',
    info: 'Lodash 是一个一致性、模块化、高性能的 JavaScript 实用工具库',
    link: 'https://www.lodashjs.com/docs/lodash.template#_templatestring-options',
    sample:
      `
        示例
        `.trim()
  },
  {
    id: 'js03',
    name: 'Dot',
    lang: 'JavaScript',
    info: '为了最快，最简洁的JavaScript模板功能，重点是在V8和Nodejs下的性能。它对Node.js和浏览器均显示出出色的性能。doT.js快速，小巧且没有依赖性。美团技术: https://tech.meituan.com/dot.html ',
    link: 'https://github.com/olado/doT',
    sample:
      `
        示例
        `.trim()
  },
  {
    id: 'js04',
    name: 'mustache',
    lang: 'JavaScript',
    info: '一个logic-less（无逻辑或轻逻辑）语法模板。具备非常多语言实现',
    link: 'https://github.com/janl/mustache.js',
    sample:
      `
        示例
        `.trim()
  },
  {
    id: 'java01',
    name: 'Freemarker',
    lang: 'java',
    info: 'FreeMarker 是一款 模板引擎： 即一种基于模板和要改变的数据， 并用来生成输出文本(HTML网页，电子邮件，配置文件，源代码等)的通用工具。 它不是面向最终用户的，而是一个java类库，是一款程序员可以嵌入他们所开发产品的组件。',
    link: 'http://freemarker.foofun.cn/',
    sample:
      `
        示例
        `.trim()
  },
  {
    id: 'java02',
    name: 'beetl3',
    lang: 'java',
    info: '功能齐全，语法直观,性能超高，以及编写的模板容易维护等特点。使得开发和维护模板有很好的体验。同时，Beetl具备引擎可定制性，可以打造自己的模板引擎。',
    link: 'http://ibeetl.com/notes/beetl/9rcjbi39/',
    sample:
      `
        示例
        `.trim()
  },
  {
    id: 'go01',
    name: 'text/template',
    lang: 'go',
    info: '内置标准库。html/template包实现了数据驱动的模板，用于生成可对抗代码注入的安全HTML输出。它提供了和text/template包相同的接口，Go语言中输出HTML的场景都应使用text/template包。',
    link: 'https://www.topgoer.com/%E5%B8%B8%E7%94%A8%E6%A0%87%E5%87%86%E5%BA%93/template.html',
    sample:
      `
        示例
        `.trim()
  },
]

const store = reactive({
  typeMappingData, typeMappingTargets,
  templateDatabaseData, templateLanguageData, databases, languages,
  dictData, itemData,
  templateEngineData
})
export default store

// 类型映射到颜色
export const typeMappingToColor = computed(() => {
  const map = new Map()
  store.typeMappingData.map(col => col.sourceTypes.split(',').forEach(type => map.set(type.trim().toUpperCase(), col.color))) // 源类型数组映射到颜色
  return map
})

// 类型映射到标准
export const typeMappingToStandard = computed(() => {
  const map = new Map()
  store.typeMappingData.forEach(col => col.sourceTypes.split(',').forEach(type => map.set(type.trim().toUpperCase(), col.code)))
  return map
})

export const templateMapping = computed(() => {
  const map = new Map()
  templateDatabaseData.forEach(row => databases.forEach(database => map.set('database-' + database + '-' + row.code, row[database] )))
  templateLanguageData.forEach(row => languages.forEach(language => map.set('language-' + language + '-' + row.code, row[language] )))
  return map
})

// 类型映射到指定数据库或编程语言
export const typeMappingToCustom = computed(() => {
  const map = new Map()
  store.typeMappingData.forEach(col => {
    col.sourceTypes.split(',').forEach(type => {
      typeMappingTargets.forEach(lang => {
        map.set((type.trim() + '-' + lang).toUpperCase(), col[lang])
      })
    })
  })
  return map
})

for (let md of typeMappingData) {
  if (md.sourceTypes.split(',').includes('xxx')) {
    return md.java
  }
}